﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Blizzard.Container;
using Blizzard.Test.DataObjects;
using Blizzard.Contracts;
using Blizzard.DAL;
using System.Configuration;
using Blizzard.Mapper;
//using NUnit.Framework;


namespace Blizzard.Test
{
    [TestClass]
    public class UnitTest1
    {
        
        private BlizzardManager manager;
        private const string _NoProperDataFound = "NO PROPER DATA HAS BEEN FOUND IN DATABASE TO DO THIS TEST";

        [TestInitialize]
        public void initializer()
        {

            string cs = ConfigurationManager.ConnectionStrings["ForSqlClientIntegratedSecurity"].ConnectionString;

          IDAO dao = new SqlClientPlugin(cs);
           //IDAO dao = new OledbPlugin(cs);
          // IDAO dao = new ODBCPlugin(cs);

          AttrMapper mapper = new AttrMapper();
          manager = new BlizzardManager(dao, mapper);
           
        }

      ///<General>
      ///<Created></Created>
      ///<Modified></Modified>
      ///<NeedsRecoredsInDatabase>Yes</NeedsRecoredsInDatabase>
      ///<UpdatesDatabase>No</UpdatesDatabase>
      ///</General>
      /// <Preparation>
      /// <step>Find one bId and its parent id (aId) in the db and save it</step>
      /// <step>Reset all the containers</step>
      /// </Preparation>
      /// <Action>
      /// <step>Use bId to load that b from db</step>
      /// <step>Create a new A (newA)</step>
      /// <step>Assign the newA as a the parent of b</step>
      /// <step>Load the original parent by its id (aId)</step>
      /// </Action>
      /// <EXPECTATION>b should not be in the list of original parent childeren</EXPECTATION>
      ///<Explanation></Explanation>
      [TestMethod]
        public void DeParentingTest()
        {
            
            //========================<PREPARATION>=======================

            //finding an existing b
            BList<B> Allbees = manager.Load<B>("");
            
            //now picking any b from the list
            B b_PREPARATION = null;
            foreach (B anyB in Allbees)
            {
                b_PREPARATION = anyB;
                break;
            }

            Assert.IsNotNull(b_PREPARATION, _NoProperDataFound);

            int bId = b_PREPARATION.Id;

            //remember that because b can not be orphen so we know that is
            //has a parent:
            int originalParentId = b_PREPARATION.aaa.Id;

            //Now resetting everything:
            manager.ResetAllContainers();

            //========================</PREPARATION>=======================


            //========================<ACTUAL TEST>========================
            //for this part see the method summary

            A newA = manager.CreateNewObject<A>();
            B b = manager.Load<B>(bId);

            b.aaa = newA;

            //------------

            A originalParent = manager.Load<A>(originalParentId);

            //now we should not see the b above in this list of the originalParent's childeren 


            foreach (B childeren in originalParent.Bees)
            {
                Assert.IsFalse(childeren.Id == bId , "DEPARENTING TEST FAILED");
            }


            //========================</ACTUAL TEST>========================

        }

      ///<General>
      ///<Created></Created>
      ///<Modified></Modified>
      ///<NeedsRecoredsInDatabase>yes</NeedsRecoredsInDatabase>
      ///<UpdatesDatabase>no</UpdatesDatabase>
      ///</General>
      ///<Preparation>
      ///<step>Load one B from database</step>
      ///</Preparation>
      ///<Action>
      ///<step>Set parent of loaded B to null</step>
      ///</Action>
      ///<Expectation>An CompositionExcepton should be thrown</Expectation>
      ///<Explanation>
      ///A null object can exist accidently. In composition relationship this means deletion for
      ///child, which should not happen, therefore we should get exception instead of deletion of child
      ///(this does not apply to a child which is not in composition relationship with parent)
      ///</Explanation>
        [TestMethod]
        [ExpectedException(typeof(CompositionException))]
        public void DeParentingByNullAssignementTest()
      {
          //to avoid interfering of other tests with this test:
          manager.ResetAllContainers();

            //=============<Preparation>=============

            BList<B> bees = manager.Load<B>("");

            B anyB = null;
            foreach (B b in bees)
            {
                anyB = b;
                break;
            }

            //=============</Preparation>=============

            anyB.aaa = null;


        }

        ///<General>
        ///<Created></Created>
        ///<Modified></Modified>
        ///<NeedsRecoredsInDatabase>yes</NeedsRecoredsInDatabase>
        ///<UpdatesDatabase>No</UpdatesDatabase>
        ///</General>
        ///<Preparation>
        ///<step>Load two bees with different parents</step>
        ///<step>keep the childeren counts of their parent for later use</step>
        ///</Preparation>
        ///<Action>
        ///<step>Assign parent of one b to parent property of the other</step>
        ///</Action>
        ///<Expectation>One of those parents should have one less child and the other should have one more</Expectation>
        ///<Explanation></Explanation>
        [TestMethod]
        public void ParentSwitchTest()
        {

            manager.ResetAllContainers();

            //===========================</PREPARATION>============================

            BList<B> Allbees = manager.Load<B>("");
            B b1 = null;
            B b2 = null;
            foreach (B b in Allbees)
            {
                b1 = b;
            }

            Assert.IsNotNull(b1, _NoProperDataFound);

            foreach (B b in Allbees)
            {
                if(b1.aaa != b.aaa)
                b2 = b;
            }
            
            Assert.IsNotNull(b2, _NoProperDataFound);

            A a1 = b1.aaa;
            A a2 = b2.aaa;

            
            int a1_OriginalBCount = a1.Bees.Count;
            int a2_OriginalBCount = a2.Bees.Count;

            //===========================</PREPARATION>============================

       
                b2.aaa = b1.aaa;

                Assert.AreEqual(a2_OriginalBCount - 1, a2.Bees.Count);
                Assert.AreEqual(a1_OriginalBCount + 1, a1.Bees.Count);
      
        }

        ///<General>
        ///<Created>1-March-2011</Created>
        ///<Modified>1-March-2011</Modified>
        ///<NeedsRecoredsInDatabase>no</NeedsRecoredsInDatabase>
        ///<UpdatesDatabase>no</UpdatesDatabase>
        ///</General>
        ///<Preparation>
        ///<step>Create one B with two C childeren</step>
        ///<step>Create another B with Three C childeren</step>
        ///</Preparation>
        ///<Action>
        ///<step>Assign the childeren of first B to the second B</step>
        ///</Action>
        ///<Expectation>Second B should have 2 childeren and first B should have zero</Expectation>
        ///<Explanation>
        ///When assigning childeren of first B to other B, we need to make sure that the childeren 
        ///of first B (who are going to have a new parent), will leave their first parent, because
        ///one child can not have more than two parents of the same type.
        ///</Explanation>
        [TestMethod]
        public void ChilderenSwitchTest()
        {
            manager.ResetAllContainers();

            //===========================<PREPARATION>============================

            B b1 = manager.CreateNewObject<B>();
            b1.Name = "b1";

            C c11 = manager.CreateNewObject<C>();
            C c12 = manager.CreateNewObject<C>();
            c11.Name = "c11";
            c12.Name = "c12";
            
            b1.Cees.Add(c11);
            b1.Cees.Add(c12);

            B b2 = manager.CreateNewObject<B>();
            b2.Name = "b2";

            C c21 = manager.CreateNewObject<C>();
            C c22 = manager.CreateNewObject<C>();
            C c23 = manager.CreateNewObject<C>();
            c21.Name = "c21";
            c22.Name = "c22";
            c23.Name = "c23";

            b2.Cees.Add(c21);
            b2.Cees.Add(c22);
            b2.Cees.Add(c23);

            //===========================</PREPARATION>============================

     

            b2.Cees = b1.Cees;

            //remember that b2 had originaly 3 cees and now it should be 2
            Assert.AreEqual(2, b2.Cees.Count);
 
            //b1 should not have any childeren
            Assert.AreEqual(0, b1.Cees.Count);

            //Original set of b2's childeren now should have parent null.



        }

        ///<General>
        ///<Created>1-March-2011</Created>
        ///<Modified>1-March-2011</Modified>
        ///<NeedsRecoredsInDatabase>no</NeedsRecoredsInDatabase>
        ///<UpdatesDatabase>no</UpdatesDatabase>
        ///</General>
        ///<Preparation>
        ///<step>Create one B with two C childeren</step>
        ///<step>Create another B with Three C childeren</step>
        ///</Preparation>
        ///<Action>
        ///<step>Add One child of first B to the other B In a loop of first B's childeren</step>
        ///</Action>
        ///<Expectation>First B should have 1 child and second B should have 4</Expectation>
        ///<Explanation></Explanation>
        [TestMethod]
        public void OneChildExchangeTest()
        {
            manager.ResetAllContainers();

            //===========================<PREPARATION>============================

            B b1 = manager.CreateNewObject<B>();
            b1.Name = "b1";

            C c11 = manager.CreateNewObject<C>();
            C c12 = manager.CreateNewObject<C>();
            c11.Name = "c11";
            c12.Name = "c12";

            b1.Cees.Add(c11);
            b1.Cees.Add(c12);

            B b2 = manager.CreateNewObject<B>();
            b2.Name = "b2";

            C c21 = manager.CreateNewObject<C>();
            C c22 = manager.CreateNewObject<C>();
            C c23 = manager.CreateNewObject<C>();
            c21.Name = "c21";
            c22.Name = "c22";
            c23.Name = "c23";

            b2.Cees.Add(c21);
            b2.Cees.Add(c22);
            b2.Cees.Add(c23);


            //===========================</PREPARATION>============================

     

            foreach (C c in b1.Cees)
            {

                b2.Cees.Add(c);
                break;

            }

            //remember that b2 had originaly 3 cees and now it should be 4
            Assert.AreEqual(4, b2.Cees.Count);

            //b1 had two childeren now it should be one
            Assert.AreEqual(1, b1.Cees.Count);


            //===========================</ActualTest>==============================
        }

                
        ///<General>
        ///<Created></Created>
        ///<Modified></Modified>
        ///<NeedsRecoredsInDatabase>yes</NeedsRecoredsInDatabase>
        ///<UpdatesDatabase>no</UpdatesDatabase>
        ///</General>
        ///<Preparation>
        ///<step>Load one A from db (should have childeren of type B)</step>
        ///<step>Get the count of Bees of A and keep it for later use</step>
        ///<step>Create two objects of type B</step>
        ///</Preparation>
        ///<Action info="two different ways of adding Bees to A">
        ///<step>Adding one of those two bees to the bees collection of A</step>
        ///<step>Assigning A as the parent of the other B</step>
        ///</Action>
        ///<Expectation>A should now have two more bees</Expectation>
        ///<Explanation></Explanation>
        [TestMethod]
        public void TwoWaysOfAddingChilderenToParentTest()
        {
  
            manager.ResetAllContainers();

            //=============================<PREPARATION>=============================

            BList<A> allAObjects = manager.Load<A>("");
            
            //checking to see whether any A object exists in database

            A a = null;
            foreach (A anyA in allAObjects)
            {
                if (anyA.Bees.Count > 0)
                {
                    a = anyA;
                    break;
                }
            }


            Assert.IsNotNull(a, _NoProperDataFound);

            //=============================</PREPARATION>=============================

            
            int count_before = a.Bees.Count;

            B newB = manager.CreateNewObject<B>();
            newB.Name = "B_" + Guid.NewGuid();

            B newB2 = manager.CreateNewObject<B>();
            newB2.Name = "B_" + Guid.NewGuid();


            //One way of adding a new b in to a's b collection
            a.Bees.Add(newB);
       
            //Another way of adding a new b in to a's b collection
            newB2.aaa = a;

         
            Assert.AreEqual(count_before + 2, a.Bees.Count);

        }

        /// <summary>
        /// ==================No DB Persistance action will happen in this test===============
        /// creating a brand-new List and a brand-new C, adding the C to that list
        /// now assigning it to an B from db (which we know that it has already a list of B)
        /// expectation: Now B should only have that brand-new C in to its BList of B.
        /// (another word, an complete BList assignement should happen)
        /// NOTE, IN THIS TEST LIST ASSIGNEMENT HAPPENS BEFORE TRIGGERING ANY LAZY LOADING ON THE ORIGINAL
        /// B'S LIST OF CEES.
        ///</summary>
        ///
        ///<General>
        ///<Created></Created>
        ///<Modified></Modified>
        ///<NeedsRecoredsInDatabase>yes</NeedsRecoredsInDatabase>
        ///<UpdatesDatabase>no</UpdatesDatabase>
        ///</General>
        ///<Preparation>
        ///<step>Load a B from db which has a non empty list of C</step>
        ///<step>keep its Id for later use</step>
        ///<step>reset all objects in blizzard</step>
        ///</Preparation>
        ///<Action info="two different ways of adding Bees to A">
        ///<step></step>
        ///<step></step>
        ///</Action>
        ///<Expectation></Expectation>
        ///<Explanation></Explanation>
        [TestMethod]
        public void ListAssignmentTest()
        {
            //we do the following to prevent any data sharing between different methods
            manager.ResetAllContainers();



            //Now, finding an B which has a none empty list of c__________________________________
            BList<B> listOfallBObjects = manager.Load<B>("");

            B b_WithAListOfCees = null;
            foreach (B any_B_WithANonEmptyListOfC in listOfallBObjects)
            {

                if (any_B_WithANonEmptyListOfC.Cees.Count > 0)
                {
                    b_WithAListOfCees = any_B_WithANonEmptyListOfC;
                    break; 
                }
            }

            Assert.IsNotNull(b_WithAListOfCees, _NoProperDataFound);

            int id_B_Object_whoHasANonEmptyListOfC = b_WithAListOfCees.Id;


            //All we did up to this moment, was the provide an id of A object in database who
            //we know it has a list of b.

            //Now to start fresh we will reset everything
            manager.ResetAllContainers();


            //______________________________________________________________________________________



      
         

            BList<C> newCList = new BList<C>(null);
            C newC = manager.CreateNewObject<C>();
            newCList.Add(newC);


            B b = manager.Load<B>(id_B_Object_whoHasANonEmptyListOfC);
            
            
            //NOTE THAT HERE BEFORE TRIGGERING ANY LAZY LOADING (for a.bees), WE ASSIGN IT TO A newBList
            b.Cees = newCList;

            foreach (C c in b.Cees)
            {
                Assert.AreSame(c, newC);
            }

            //extera check:
            Assert.AreEqual(1, b.Cees.Count);




            //avoiding any further action on the objects of this test method, in other test methods:
            manager.ResetAllContainers();

        }

        /// <summary>
        /// ==================No DB Persistance action will happen in this test===============
        /// creating a brand-new BList and a brand-new C, adding the C to that list
        /// now assigning it to an B from db (which we know that it has already a list of C)
        /// now all those original bees should have no parent (deParenting through list assignment)
        /// </summary>
        [TestMethod]
        public void DeparentingByListAssignment()
        {

            //we do the following to prevent any data sharing between different methods
            manager.ResetAllContainers();



            //Now, finding an A which has a none empty list of b___________________________________
            BList<B> listOfallBObjects = manager.Load<B>("");

            B b_WithAListOfCees = null;
            foreach (B any_B_WithANonEmptyListOfC in listOfallBObjects)
            {

                if (any_B_WithANonEmptyListOfC.Cees.Count > 0)
                    b_WithAListOfCees = any_B_WithANonEmptyListOfC;

            }

            Assert.IsNotNull(b_WithAListOfCees, _NoProperDataFound);

            int id_B_Object_whoHasANonEmptyListOfC = b_WithAListOfCees.Id;

            
            //All we did up to this moment, was the provide an id of B object in database who
            //we know it has a list of c.

            //______________________________________________________________________________________


            //Now to start fresh we will reset everything
            manager.ResetAllContainers();

           


            BList<C> newCList = new BList<C>(null);
            C newC = manager.CreateNewObject<C>();
            newCList.Add(newC);

            B b = manager.Load<B>(id_B_Object_whoHasANonEmptyListOfC);
            

            //NOTE THAT THE FOLLOWING ACTION WILL ALSO TRIGGER THE LAZYLOADING OF a.bees
            BList<C> originalChilderen = b.Cees;



            b.Cees = newCList;

         

            BList<C> BListfromB = b.Cees;

            foreach (C c in originalChilderen)
            {
                Assert.IsNull(c.bbb  , "DEPARENTING TEST THROUGH LIST ASSIGNMENT FAILED");
            }



            //avoiding any further action on the objects of this test method, in other test methods:
            manager.ResetAllContainers();


        }


    

        /// <summary>
        /// We load an A object from db, we get the bee counts of it.
        /// now we intanciate a brand new b and we set above A object in to its aaa property.
        /// WE update it to db, now we load once again the original A from db. 
        /// 
        /// EXPECTATION: A should have one more b in its bees collection. (that proves the persistance of 
        /// b item to db as A's child.
        /// </summary>
        [TestMethod]
        public void PersistanceTestThroughParentassignement()
        {
            
            manager.ResetAllContainers();

            //First finding an random a in database
            BList<A> listOfAllAObjects = manager.Load<A>("");
            A a_BeforeUpdate = null;

            foreach (A someA in listOfAllAObjects)
            {
                //The first A found in db is good enogh
                a_BeforeUpdate = someA;
            }

            Assert.IsNotNull(a_BeforeUpdate, _NoProperDataFound);

            int id_a = a_BeforeUpdate.Id;//for later use

            int count_beforeUpdate = a_BeforeUpdate.Bees.Count;

            B newB = manager.CreateNewObject<B>();
            newB.aaa = a_BeforeUpdate;
            newB.Name = "B_" + Guid.NewGuid();

            manager.UpdateAndReset();

            A a_AfterUpdate = manager.Load<A>(id_a);
            int count_afterUpdate = a_AfterUpdate.Bees.Count;

            Assert.AreEqual(count_afterUpdate, count_beforeUpdate + 1 , "PERSISTANCE FAILED");

        }


        /// <summary>
        /// =====================DATABASE PERSISTANCE HAPPENS IN THIS TEST==================
        /// 
        /// We Load One B from database, then we assign a newly created list of cees (containing 3 c) (fresh and detached) to
        /// cees property of that B and we persist it into database.
        ///
        /// Expectation: after relaoding the same B from database we should have 3 cees in Cees property of B
        /// who have the same names.
        /// </summary>
        [TestMethod]
        public void PersistanceTestThroughListAssignement()
        {
            
            manager.ResetAllContainers();


            //First finding an random a in database
            BList<B> listOfAllBObjects = manager.Load<B>("");
            B b_BeforeUpdate = null;

            foreach (B someB in listOfAllBObjects)
            {
                //The first A found in db is good enogh
                b_BeforeUpdate = someB;
                break;
            }

            Assert.IsNotNull(b_BeforeUpdate, _NoProperDataFound);

            int id_b = b_BeforeUpdate.Id;

           

            BList<C> newcees = new BList<C>(null);

            C c1 = manager.CreateNewObject<C>();
            C c2 = manager.CreateNewObject<C>();
            C c3 = manager.CreateNewObject<C>();
      
            c1.Name = "C_" + Guid.NewGuid();
            c2.Name = "C_" + Guid.NewGuid();
            c3.Name = "C_" + Guid.NewGuid();


            newcees.Add(c1);
            newcees.Add(c2);
            newcees.Add(c3);


            b_BeforeUpdate.Cees = newcees;


            //remember that by resetting all containers in the following line 
            //the above newbees list and its b contents
            //will be removed from containers, but they still in scope here so
            //they will not be destroyed in this method, thats why we still can use
            //them later.
            manager.UpdateAndReset();

            //==============reloading the same a from db and test=====================

            B b_AfterUpdate = manager.Load<B>(id_b);

            int counter = 0;
            foreach (C persisted_c in b_AfterUpdate.Cees)
            {
                foreach (C c in newcees)
                {
                    if (c.Name == persisted_c.Name)
                    {
                        counter++;
                    }
                }
            }

            Assert.AreEqual(3, counter, "PERSISTANCE TEST THROUGH LIST ASSIGNEMENT FAILED");
        }


        /// <summary>
        /// creats brand new objects, first one A and then two Bees and for one of those bees one c
        /// for the other bee two cees, in the end updates it in to db (this is a complete insertion of
        /// hirarcy objects (ABC).
        /// it recognizes objects based on their name (which is a guid name)
        /// </summary>
        [TestMethod]
        public void MasterInsertTest() // selfsufficient
        {
            
            manager.ResetAllContainers();


            A a = manager.CreateNewObject<A>();
            a.Name = "A_" + Guid.NewGuid();

            //==================

            B b1 = manager.CreateNewObject<B>();
            B b2 = manager.CreateNewObject<B>();
            B b3 = manager.CreateNewObject<B>();

            b1.Name = "B_" + Guid.NewGuid();
            b2.Name = "B_" + Guid.NewGuid();
            b3.Name = "B_" + Guid.NewGuid();

            //==================

            C c1 = manager.CreateNewObject<C>();
            C c2 = manager.CreateNewObject<C>();
            C c3 = manager.CreateNewObject<C>();

            c1.Name = "C_" + Guid.NewGuid();
            c2.Name = "C_" + Guid.NewGuid();
            c3.Name = "C_" + Guid.NewGuid();

            //===================

            CC cc1 = manager.CreateNewObject<CC>();
            CC cc2 = manager.CreateNewObject<CC>();
            CC cc3 = manager.CreateNewObject<CC>();

            cc1.Name = "CC_" + Guid.NewGuid();
            cc2.Name = "CC_" + Guid.NewGuid();
            cc3.Name = "CC_" + Guid.NewGuid();

            //===================

            D d1 = manager.CreateNewObject<D>();
            D d2 = manager.CreateNewObject<D>();
            D d3 = manager.CreateNewObject<D>();

            d1.Name = "D_" + Guid.NewGuid();
            d2.Name = "D_" + Guid.NewGuid();
            d3.Name = "D_" + Guid.NewGuid();

            //===================

            //two different ways of adding bees to a
            b1.aaa = a;
            b2.aaa = a;
            a.Bees.Add(b3); 


            //Adding Cees to bees:

            b1.Cees.Add(c1);

            //two different ways of adding cees to b2 (no c for b3)
            b2.Cees.Add(c2);
            c3.bbb = b2;

            //================================

            //Just to make it different, first adding Dees to CCees and then
            //adding CCees to Bees

            cc1.Dees.Add(d1);
            d2.ccc = cc2;
            d3.ccc = cc3;
            
            
         
            //Adding CCees to bees:

            b1.CCees.Add(cc1);

            //two different ways of adding cees to b2 (no c for b3)
            b2.CCees.Add(cc2);
            cc3.bbb = b2;

            //=============================

            //========================================================================
            //========================================================================
            manager.UpdateAndReset();
            //========================================================================
            //========================================================================

            //now relaoding objects and test them:-------------------------------->

            BList<A> aaz = manager.Load<A>(""); //loads all A objects

            A reloaded_a = null;

            foreach (A aa in aaz)
            {
                if (aa.Name == a.Name)
                    reloaded_a = aa;
            }

            Assert.IsNotNull(reloaded_a);

            
            //now checking if the bees in a are exactly those that we made above

            B reloaded_b1 = null;
            B reloaded_b2 = null;
            B reloaded_b3 = null;

            foreach (B reloadedB in reloaded_a.Bees)
            {
                if (reloadedB.Name == b1.Name)
                    reloaded_b1 = reloadedB;

                if (reloadedB.Name == b2.Name)
                    reloaded_b2 = reloadedB;

                if (reloadedB.Name == b3.Name)
                    reloaded_b3 = reloadedB;
            }


            Assert.IsNotNull(reloaded_b1);
            Assert.IsNotNull(reloaded_b2);
            Assert.IsNotNull(reloaded_b3);

            //==================================================

            C reloaded_c1 = null;
            C reloaded_c2 = null;
            C reloaded_c3 = null;

            foreach (C reloadedC in reloaded_b1.Cees)
            {
                if (reloadedC.Name == c1.Name)
                    reloaded_c1 = reloadedC;
            }
            foreach (C reloadedC in reloaded_b2.Cees)
            {
                if (reloadedC.Name == c2.Name)
                    reloaded_c2 = reloadedC;

                if (reloadedC.Name == c3.Name)
                    reloaded_c3 = reloadedC;
            }

            Assert.IsNotNull(reloaded_c1);
            Assert.IsNotNull(reloaded_c2);
            Assert.IsNotNull(reloaded_c3);

         



        }
        

        /// <summary>
        ///     =====================persistance to db happens here=====================
        /// inserting one object who basically per defenition has childeren (no parents though)
        /// but it has not any instance of any relation (an empty list of childeren)
        /// </summary>
        [TestMethod]
        public void OneObjectInsertTest()
        {

            manager.ResetAllContainers();


            A a = manager.CreateNewObject<A>();
            a.Name = "A" + Guid.NewGuid();

            manager.UpdateAndReset();

            //=========================

            //now relaoding objects and test them:-------------------------------->

            BList<A> aaz = manager.Load<A>(""); //loads all A objects

            A reloaded_a = null;

            foreach (A aa in aaz)
            {
                if (aa.Name == a.Name)
                    reloaded_a = aa;
            }

            Assert.IsNotNull(reloaded_a);


        }

        /// <summary>
        ///     =====================persistance to db happens here=====================
        /// inserting one object who per defenition has no any relation with any other Idataobject
        /// 
        /// </summary>
        [TestMethod]
        public void OneObjectInsertTestII()
        {

            manager.ResetAllContainers();


            X x = manager.CreateNewObject<X>();
            x.Name = "X_" + Guid.NewGuid();

            manager.UpdateAndReset();

            //=========================

            //now relaoding objects and test them:-------------------------------->

            BList<X> exes = manager.Load<X>(""); //loads all X objects

            X reloaded_x = null;

            foreach (X xx in exes)
            {
                if (xx.Name == x.Name)
                    reloaded_x = xx;
            }

            Assert.IsNotNull(reloaded_x);


        }
        
        /// <summary>
        /// A try for insertin of an object which is involved in a Aggrogation Composition
        /// relationship with its parent, execution of this test metod should result to
        /// an exeption.
        /// </summary>
        
        //[ExpectedException(typeof(AggregateException))]  // USE THIS (NOW I DONT HAVE TIME TO CHECK IT PROBABLY BUT YOU SHOULD TAKE A LOOK AT THAT)
        [TestMethod]
        public void InsertABrandNewChildInCompositeRelationWithoutParent()
        {

            manager.ResetAllContainers();

            C c = manager.CreateNewObject<C>();
            B b = manager.CreateNewObject<B>();
            
            
            b.Name = "B_" + Guid.NewGuid();
            c.Name = "C_" + Guid.NewGuid();

            c.bbb = b;

            try
            {
                manager.UpdateAndReset();
                Assert.Fail();
            }
            catch (Exception  ex)
            {
                Assert.IsTrue(ex.GetType() == typeof(CompositionException));
            }
            
            

        }

        /// <summary>
        /// A brand new child which is not involved in a composite relation, and also has a parent of null
        /// should have 0 (and not null) in database for the field who referes to parent.
        /// </summary>
        [TestMethod]
        public void InsertABrandNewChildWithoutPerent()
        {
            manager.ResetAllContainers();

            C c = manager.CreateNewObject<C>();

            c.Name = "C__WithoutB__" + Guid.NewGuid();
            string name_forlateruse = c.Name;

            manager.UpdateAndReset();

            // now testing whether the parent id in database is set on 0

            BList<C> cees = manager.Load<C>("");


            //foreach (C cc in cees)
            //{
            //    if (cc.Name == name_forlateruse)
            //    {
            //        Assert.AreEqual<int>()
            //    }
            //}

            // if the bID in database for this c is 0 then this test is passed (which is so)
            Assert.Inconclusive("TO SEE WHETHER THIS TEST PASSES, DATABASE SHOULD BE CHECKED DIRECTLY");

        }


        /// <summary>
        /// This Test method does not need any preExecution.
        /// </summary>
        [TestMethod]
        public void ManyToManyInsertTest() // selfsufficient
        {
            //This Test method does not need any preExecution.
            //that it; it can be Singled out and executed on an empty database.

            manager.ResetAllContainers();

            //We need to set a parent for b because B types need a parent (but not BB types)
            A a = manager.CreateNewObject<A>();
            a.Name = "A_" + Guid.NewGuid();

            B b = manager.CreateNewObject<B>();
            b.Name = "B_" + Guid.NewGuid();
            b.aaa = a;


            BB bb1 = manager.CreateNewObject<BB>();
            BB bb2 = manager.CreateNewObject<BB>();
            BB bb3 = manager.CreateNewObject<BB>();
            BB bb4 = manager.CreateNewObject<BB>();

            bb1.Name = "BB_" + Guid.NewGuid();
            bb2.Name = "BB_" + Guid.NewGuid();
            bb3.Name = "BB_" + Guid.NewGuid();
            bb4.Name = "BB_" + Guid.NewGuid();

            bb1.DateAdded = DateTime.Parse(DateTime.Now.ToString("dd-MM-yyyy"));
            bb2.DateAdded = DateTime.Parse(DateTime.Now.ToString("dd-MM-yyyy"));
            bb3.DateAdded = DateTime.Parse(DateTime.Now.ToString("dd-MM-yyyy"));
            bb4.DateAdded = DateTime.Parse(DateTime.Now.ToString("dd-MM-yyyy"));

            bb1.Bees.Add(b);
            bb2.Bees.Add(b);

            b.BBees.Add(bb3);
            b.BBees.Add(bb4);

            manager.Update();

            int b_id = b.Id;

            List<int> bb_ids = new List<int>();
            bb_ids.Add(bb1.Id);
            bb_ids.Add(bb2.Id);
            bb_ids.Add(bb3.Id);
            bb_ids.Add(bb4.Id);
                        
            //Now testing the resulted data:--------------------->
            //checking whether b has a list of 4 bb's that we just coupled to eachother:

            //Loading the above inserted b from database again
            B inserted_b = manager.Load<B>(b_id);

            foreach (BB bb in inserted_b.BBees)
            {
                //Assert.AreEqual<bool>(true, bb_ids.Contains(bb.Id), "many to many relations has not been persisted properly");
                Assert.IsTrue(bb_ids.Contains(bb.Id), "many to many relations has not been persisted properly");
            }


        }

        /// <summary>
        /// ==================DATABASE PERSISTANCE WILL HAPPEN HERE======================
        /// We load one B and one BB object from database (many to many relationship)
        /// now we use Remove method of The BList to remove one of them from the the others list
        /// we update objects to database
        /// 
        /// Expectation:
        /// after reloading one of them, the other should not be in its list.
        /// </summary>
        [TestMethod]
        public void ManyToManyUpdateAfterCallingToRemoveMethodTest()
        {
            manager.ResetAllContainers();

            //======================<PREPARATION>=======================

            BList<BB> Allbbees = manager.Load<BB>("");
            
            //cheking whether any BB exists in database________
            BB bb = null;
            foreach (BB anyBB in Allbbees)
            {
                bb = anyBB;
                
                if(bb.Bees.Count>0)
                break;
            }

            Assert.IsNotNull(bb, _NoProperDataFound);
            //__________________________________________________

            //cheking whether the BB has anyrelation with any B
            B b = null;
            foreach (B anyB in bb.Bees)
            {
                b = anyB;
                break;
            }
            Assert.IsNotNull(b, _NoProperDataFound);
            //__________________________________________________

            int bbId = bb.Id;
            int bId = b.Id;

            //======================</PREPARATION>=======================

           
            b.BBees.Remove(bb);
            manager.UpdateAndReset();


            //now cheking whether it is persisted:
            BB bb_reloaded = manager.Load<BB>(bbId);

            B b_Test = null;
            foreach (B bee in bb_reloaded.Bees)
            {
                if (bee.Id == bId)
                    b_Test = bee;
            }

            Assert.IsNull(b_Test, "TEST FAILED");

        }

   
        [TestMethod]
        public void SimplePropertyUpdateTest()
        {
            manager.ResetAllContainers();

            //========================<PREPARATION>=======================

            //finding an existing b
            BList<B> Allbees = manager.Load<B>("");

            //now picking any b from the list
            B b_PREPARATION = null;
            foreach (B anyB in Allbees)
            {
                b_PREPARATION = anyB;
                break;
            }

            //checking to see whether at least one b exists in database
            Assert.IsNotNull(b_PREPARATION, _NoProperDataFound);
            
            int bId = b_PREPARATION.Id;

            manager.ResetAllContainers();

            //========================</PREPARATION>=======================



            B b = manager.Load<B>(bId);

            string name = "B_" + Guid.NewGuid();
            b.Name = name;

            manager.UpdateAndReset();


            B b_Reloaded = manager.Load<B>(bId);

            Assert.AreEqual(name, b_Reloaded.Name);


        }

        [TestMethod]
        public void DateTimePropertyUptateTest()
        {
            manager.ResetAllContainers();

            //========================<PREPARATION>=======================

            //finding an existing b
            BList<BB> Allbbees = manager.Load<BB>("");

            //now picking any b from the list
            BB bb_PREPARATION = null;
            foreach (BB anyBB in Allbbees)
            {
                bb_PREPARATION = anyBB;
                break;
            }

            //checking to see whether at least one b exists in database
            Assert.IsNotNull(bb_PREPARATION, _NoProperDataFound);

            int bbId = bb_PREPARATION.Id;

            manager.ResetAllContainers();

            //========================</PREPARATION>=======================

            BB bb = manager.Load<BB>(bbId);

            DateTime myTime = DateTime.Parse(DateTime.Now.ToString("dd-MM-yyyy")); 
            bb.DateAdded = myTime;

            manager.UpdateAndReset();



            BB bb_reloaded = manager.Load<BB>(bbId);


            //==============11 June 2011==================
            //STRANGE, IT SEEMS THAT THIS NOW PASSES,...SO FOLLOWING COMMENT IS NOT VALID ANY MORE????
            //============================================

           // Assert.Inconclusive("THIS SHOULD BASICALLY PASS, PLEASE READ THE COMMENT IN THE METHOD");

            //the following two parameters have slightly different values, thats why
            //it does not pass, if you see database and also the comparison even by 
            //unittest message, you will not see any diff (the diff is in miliseconds (sometimes
            //they are different, but the ticks are always different )

            //so basically this test should pass
            Assert.AreEqual(myTime, bb_reloaded.DateAdded, "THIS SHOULD BASICALLY PASS, PLEASE READ THE COMMENT IN THE METHOD");

            
        
        }


        [TestMethod]
        public void ObjectDeletion()
        {

            //============<PREPARATION>================
            A a = manager.CreateNewObject<A>();
            string name =  "AAA_" + Guid.NewGuid();
            a.Name = name;


            manager.UpdateAndReset();
            //============</PREPARATION>================

            BList<A> listOfA = manager.Load<A>("where name ='" + name + "'");
           
           A aLoad = (listOfA.Count > 0)? listOfA[0]: null;

            manager.MarkForDeletion(aLoad);
            manager.UpdateAndReset();

            // attempt to reload again for existance check
            BList<A> aRelads = manager.Load<A>("where name ='" + name + "'");
            A aReload = (aRelads.Count > 0)? aRelads[0]: null;

            Assert.IsNull(aReload);
        }

        /// <summary>
        /// In this test we Break a relation between two objects (both loaded from database)
        /// and reasseign two objects later again (we create the previous relation again)
        /// </summary>
        [TestMethod]
        public void BreakAndMakeRelations()
        {
            manager.ResetAllContainers();

            //=======================================<PREPARATION>====================
            BList<B> allBees = manager.Load<B>("");

            //picking one:
            Assert.IsTrue(allBees.Count != 0, "There is No B Object in DB, This happens Only the first time");
            B b = allBees[0];

            //Loading some related A:
            A a = b.aaa;
            //=======================================</PREPARATION>====================

            //Now we have two objects loaded from db and we are going to break their relationship:
            b.aaa = manager.CreateNewObject<A>();

            //Now we are going to reconnect the original objects:
            b.aaa = a;

            Assert.AreSame(b.aaa, a);
        }


        [TestMethod]
        public void EnumDataType()
        {

            manager.ResetAllContainers();

            Person p = manager.CreateNewObject<Person>();

            p.Name = "Now me";
            p.Character = GBU.Good ;
            p.FavoriteColor = Color.Green;

            manager.UpdateAndReset();

            manager.dataTypeMapper += new EnumDataConvertorDelegate(DataTypeMapperImplementation);
            BList<Person> people = manager.Load<Person>("");

            if (people.Count > 0)
            {
                Person lastPersonIndb = people[people.Count - 1];
                
                Assert.AreEqual(lastPersonIndb.Character, GBU.Good);
                Assert.AreEqual(lastPersonIndb.FavoriteColor, Color.Green);
            }
            else
            {
                Assert.Fail("No person loaded");
            }
                

        }
      
        private object DataTypeMapperImplementation(Type EnumTypeOfProperty, object propertyYalue)
        {
            if (EnumTypeOfProperty == typeof(GBU))
            {
              
                switch (propertyYalue.ToString())
                {
                    case "Good":
                        return GBU.Good;

                    case "Bad":
                        return GBU.Bad;

                    case "Ugly":
                        return GBU.Ugly;
                }

            }
            else if (EnumTypeOfProperty == typeof(Color))
            {
                switch (propertyYalue.ToString())
                {
                    case "Green":
                        return Color.Green;

                    case "Blue":
                        return Color.Blue;

                    case "Yellow":
                        return Color.Yellow;
                }
            }

            return null;
        }


        /// <summary>
        /// NEEDS DATA IN DATABASE
        /// Precondition:   We have a B which is in the Bees list of some A,...this B has an associated BB.
        /// Action:         We remove this B from the Bees of A
        /// Expectation:    Because B and A have composite relationship, when you remove the B from childeren of A, it becomes
        /// orphan. and since an orphan B should not exist,...we should not find it in any other relationship, in this case
        /// we should not find it in BB's list of Bees
        /// </summary>
        [TestMethod]
        public void OrphansShouldBeMarkedForDeletion()
        {

            manager.ResetAllContainers();

            //==============<PREPERATION>===============
            //First finding an random a in database
            BList<A> listOfAllAObjects = manager.Load<A>("");
            A a_RandomA = null;

            foreach (A a in listOfAllAObjects)
            {
                //The first A with a B who has a BB is good enough

                foreach (B b in a.Bees)
                {
                    if (b.BBees.Count != 0)
                    {
                        a_RandomA = a;
                        break;
                    }
                }
               
            }

            Assert.IsNotNull(a_RandomA, _NoProperDataFound);//========================

            B b_RandomChild = null;
            foreach (B b in a_RandomA.Bees)
            {

                if (b.BBees.Count != 0)
                {
                    b_RandomChild = b;
                    break;
                }
            }

            Assert.IsNotNull(b_RandomChild, _NoProperDataFound);//====================


            BB BB_Associated = null;
            foreach (BB bb in b_RandomChild.BBees)
            {
                //any first BB is ok
                BB_Associated = bb;
                break;

            }

            Assert.IsNotNull(BB_Associated, _NoProperDataFound);//====================

            //keeping the id for later use
            int bId = b_RandomChild.Id;

   
            //==============</PREPERATION>===============
        
        
            //Now we have an A and a B child and a BB asscociate of B

            //In the following line we remove b_RandomChild from list of childeren of A
            //because b_RandomChild involves in a composition relation it can not remain
            //orphan, there for in the later test when trying to find all the associates 
            // of BB_Associated, the b_RandomChild should not be there (based on its id)
            a_RandomA.Bees.Remove(b_RandomChild);

            foreach (B b in BB_Associated.Bees)
            {
                if (b.Id == bId)
                {
                    Assert.Fail("An Orphan B object should not be available");
                    return;
                }
    
            }

            
        }

        /// <summary>
        /// NEEDS DATA IN DATABASE
        /// Precondition:   We have a B which is in the Bees list of some A,...this B has a CC child and that CC has a D child
        /// Action:         We remove this B from the Bees of A
        /// Expectation:    Because B and A have composite relationship, when you remove the B from childeren of A, it becomes
        /// orphan. and since an orphan B should not exist,...no composite childeren of him should exist, and since CC has
        /// a composite relation with B, all CC childeren of B also should not be available in any relation ship.
        /// we test this later, by checking whether the parent of D (which is a CC) is null (null will pass the test)
        /// </summary>
        [TestMethod]
        public void OrphansShouldBeMarkedForDeletion2()
        {

            manager.ResetAllContainers();

            //==============<PREPERATION>===============
            //First finding an qualified a in database
            BList<A> listOfAllAObjects = manager.Load<A>("");
            A a_QualifiedA = null;

            foreach (A a in listOfAllAObjects)
            {
                //The first A with a B who has a BB and CC (whoes cc has ddees) is good enough

                foreach (B b in a.Bees)
                {
                    if (b.CCees.Count != 0)
                    {

                        foreach (CC cc in b.CCees)
                        {

                            if (cc.Dees.Count != 0)
                            {
                                a_QualifiedA = a;
                                break;

                            }

                        }


                    }
                }

            }

            Assert.IsNotNull(a_QualifiedA, _NoProperDataFound);//========================


            //now finding a qualified B

            B b_QualifiedB = null;
            foreach (B b in a_QualifiedA.Bees)
            {
                if (b.CCees.Count != 0)
                {

                    foreach (CC cc in b.CCees)
                    {

                        if (cc.Dees.Count != 0)
                        {
                            b_QualifiedB = b;
                            break;

                        }

                    }


                }
            }

            Assert.IsNotNull(b_QualifiedB, _NoProperDataFound);//========================

            //finding a qualified CC

            CC cc_QualifiedCC = null;
            foreach (CC cc in b_QualifiedB.CCees)
            {

                if (cc.Dees.Count != 0)
                {
                    cc_QualifiedCC = cc;
                    break;

                }

            }

            Assert.IsNotNull(cc_QualifiedCC, _NoProperDataFound);//========================

            //finding the dd that is going to be tested later

            D d_TestSubject = null;

            //any first D in the following loop is qualified
            foreach (D d in cc_QualifiedCC.Dees)
            {
                d_TestSubject = d;
                break;
            }

            Assert.IsNotNull(d_TestSubject, _NoProperDataFound);//========================

            //==============</PREPERATION>===============


            //==============<Actual Test>===============


            a_QualifiedA.Bees.Remove(b_QualifiedB);
           
            //at this point we should expect that our previous quelified B is orphan and therefore
            // not only it should be marked as deleted (which in our case means it should not be available
            //any more, but also all its CC childeren (which are in composition relation with B) should
            //also not be available any more

            //ACTUALLY BY TESTING THE NON AVAILABILITY OF THE CCEES WE CAN CONCLUD THAT THE B IS ALSO
            //NOT AVAILABLE (BECAUSE BEES NOT AVAILIBILITY IS THE VERY RESEAN OF NOT AVAILIBILITY OF CC

            Assert.IsNull(d_TestSubject.ccc , "An Orphan CC object should not be available");

            //==============</Actual Test>===============

        }

        /// <summary>
        /// NEEDS DATA IN DATABASE
        /// Precondition:   We have a B which is in the Bees list of some A,...this B has an associated BB.
        /// Action:         We Delete the A
        /// Expectation:    Because B and A have composite relationship, when you remove the B from childeren of A, it becomes
        /// orphan. and since an orphan B should not exist,...we should not find it in any other relationship, in this case
        /// we should not find it in BB's list of Bees
        /// </summary>
        [TestMethod]
        public void OrphansShouldBeMarkedForDeletion3()
        {

            manager.ResetAllContainers();

            //==============<PREPERATION>===============
            //First finding an random a in database
            BList<A> listOfAllAObjects = manager.Load<A>("");
            A a_RandomA = null;

            foreach (A a in listOfAllAObjects)
            {
                //The first A with a B who has a BB is good enough

                foreach (B b in a.Bees)
                {
                    if (b.BBees.Count != 0)
                    {
                        a_RandomA = a;
                        break;
                    }
                }

            }

            Assert.IsNotNull(a_RandomA, _NoProperDataFound);//========================

            B b_RandomChild = null;
            foreach (B b in a_RandomA.Bees)
            {

                if (b.BBees.Count != 0)
                {
                    b_RandomChild = b;
                    break;
                }
            }

            Assert.IsNotNull(b_RandomChild, _NoProperDataFound);//====================


            BB BB_Associated = null;
            foreach (BB bb in b_RandomChild.BBees)
            {
                //any first BB is ok
                BB_Associated = bb;
                break;

            }

            Assert.IsNotNull(BB_Associated, _NoProperDataFound);//====================

            //keeping the id for later use
            int bId = b_RandomChild.Id;


            //==============</PREPERATION>===============


            //Now we have an A and a B child and a BB asscociate of B

            //In the following line we Delete A
            //because b_RandomChild involves in a composition relation it can not remain
            //orphan, therefor in the later test when trying to find all the associates 
            // of BB_Associated, the b_RandomChild should not be there (based on its id)
            manager.MarkForDeletion(a_RandomA);

            foreach (B b in BB_Associated.Bees)
            {
                if (b.Id == bId)
                {
                    Assert.Fail("An Orphan B object should not be available");
                    return;
                }

            }


        }

    }
}
